{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-12-30T05:03:52.653016Z",
     "start_time": "2019-12-30T05:03:52.292979Z"
    }
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-12-30T05:03:52.660514Z",
     "start_time": "2019-12-30T05:03:52.655012Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([[ 0,  0],\n",
       "        [ 0, -1],\n",
       "        [ 1,  1],\n",
       "        [-1,  0],\n",
       "        [ 0,  1]]), array([ 1,  1,  1, -1, -1]))"
      ]
     },
     "execution_count": 77,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = np.asarray([[0,0],[0,-1],[1,1],[-1,0],[0,1]])\n",
    "y = np.asarray([1,1,1,-1,-1])\n",
    "x,y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 205,
   "metadata": {},
   "outputs": [],
   "source": [
    "xx = np.arange(-1,1,0.1)\n",
    "yy = xx+0.5\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 206,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-12-30T05:03:52.862963Z",
     "start_time": "2019-12-30T05:03:52.661502Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(-2, 2)"
      ]
     },
     "execution_count": 206,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.plot(xx,yy)\n",
    "plt.scatter(x[:,0],x[:,1],c=y)\n",
    "plt.xlim(-2,2)\n",
    "plt.ylim(-2,2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-12-30T05:03:52.866980Z",
     "start_time": "2019-12-30T05:03:52.863960Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 1],\n",
       "       [ 1],\n",
       "       [-1],\n",
       "       [-1]])"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y = y.reshape(-1,1)\n",
    "y"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 第一种用numpy的做法 $A(\\alpha)=\\sum_{i=1}^{n}\\alpha_i - \\frac{1}{2}\\sum_{i=1}^{n}\\sum_{j=1}^{n}\\alpha_i\\alpha_j y_i y_j x_i^T x_j$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-12-30T05:03:52.874931Z",
     "start_time": "2019-12-30T05:03:52.867950Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  0,  0,  0],\n",
       "       [ 0,  2, -1,  1],\n",
       "       [ 0, -1,  1,  0],\n",
       "       [ 0,  1,  0,  1]])"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "xij = x.dot(x.T)\n",
    "xij"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-12-30T05:03:52.880947Z",
     "start_time": "2019-12-30T05:03:52.875928Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 1,  1, -1, -1],\n",
       "       [ 1,  1, -1, -1],\n",
       "       [-1, -1,  1,  1],\n",
       "       [-1, -1,  1,  1]])"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "yij = y.dot(y.T)\n",
    "yij"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-12-30T05:03:52.886899Z",
     "start_time": "2019-12-30T05:03:52.882937Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  0,  0,  0],\n",
       "       [ 0,  2,  1, -1],\n",
       "       [ 0,  1,  1,  0],\n",
       "       [ 0, -1,  0,  1]])"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A = yij*xij\n",
    "A"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-12-30T05:03:52.894878Z",
     "start_time": "2019-12-30T05:03:52.888894Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2 a2^2\n",
      "2 a2a3\n",
      "-2 a2a4\n",
      "1 a3^2\n",
      "1 a4^2\n"
     ]
    }
   ],
   "source": [
    "for i in range(A.shape[0]):\n",
    "    for j in range(i,A.shape[1]):\n",
    "        if i == j:\n",
    "            coef = A[i][i]\n",
    "            if coef !=0:\n",
    "                print(f\"{coef} a{i+1}^2\")\n",
    "        else:\n",
    "            coef = A[i][j] + A[j][i]            \n",
    "            if coef !=0:\n",
    "                print(f\"{coef} a{i+1}a{j+1}\")\n",
    "# 手算求导下去"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 第二种sympy符号计算 $A(\\alpha)=\\sum_{i=1}^{n}\\alpha_i - \\frac{1}{2}\\sum_{i=1}^{n}\\sum_{j=1}^{n}\\alpha_i\\alpha_j y_i y_j x_i^T x_j$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 255,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-12-30T05:03:52.900890Z",
     "start_time": "2019-12-30T05:03:52.895875Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([[ 0,  0],\n",
       "        [ 0, -1],\n",
       "        [ 1,  1],\n",
       "        [-1,  0],\n",
       "        [ 0,  1]]), array([ 1,  1,  1, -1, -1]))"
      ]
     },
     "execution_count": 255,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = np.asarray([[0,0],[0,-1],[1,1],[-1,0],[0,1]])\n",
    "y = np.asarray([1,1,1,-1,-1])\n",
    "x,y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 256,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-12-30T05:03:53.426485Z",
     "start_time": "2019-12-30T05:03:52.901859Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle a_{1}$"
      ],
      "text/plain": [
       "a_1"
      ]
     },
     "execution_count": 256,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import sympy\n",
    "a = sympy.symbols(\"a_1 a_2 a_3 a_4 a_5\") \n",
    "a[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 257,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-12-30T05:03:53.468474Z",
     "start_time": "2019-12-30T05:03:53.427455Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle a_{1} + a_{2} + a_{3} + a_{4} + a_{5}$"
      ],
      "text/plain": [
       "a_1 + a_2 + a_3 + a_4 + a_5"
      ]
     },
     "execution_count": 257,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "eq1 = sympy.Add(*a)\n",
    "eq1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 258,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-12-30T05:03:53.683928Z",
     "start_time": "2019-12-30T05:03:53.469470Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle a_{2}^{2} - 2 a_{2} a_{3} + 2 a_{2} a_{5} + 2 a_{3}^{2} + 2 a_{3} a_{4} - 2 a_{3} a_{5} + a_{4}^{2} + a_{5}^{2}$"
      ],
      "text/plain": [
       "a_2**2 - 2*a_2*a_3 + 2*a_2*a_5 + 2*a_3**2 + 2*a_3*a_4 - 2*a_3*a_5 + a_4**2 + a_5**2"
      ]
     },
     "execution_count": 258,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "eq = []\n",
    "for i in range(x.shape[0]):\n",
    "    for j in range(x.shape[0]):\n",
    "        eq.append(a[i]*a[j]*y[i]*y[j]*(x[i]*x[j]).sum())\n",
    "eq2 = sympy.Add(*eq)\n",
    "eq2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 259,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-12-30T05:03:53.694868Z",
     "start_time": "2019-12-30T05:03:53.684935Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle a_{1} - 0.5 a_{2}^{2} + 1.0 a_{2} a_{3} - 1.0 a_{2} a_{5} + a_{2} - 1.0 a_{3}^{2} - 1.0 a_{3} a_{4} + 1.0 a_{3} a_{5} + a_{3} - 0.5 a_{4}^{2} + a_{4} - 0.5 a_{5}^{2} + a_{5}$"
      ],
      "text/plain": [
       "a_1 - 0.5*a_2**2 + 1.0*a_2*a_3 - 1.0*a_2*a_5 + a_2 - 1.0*a_3**2 - 1.0*a_3*a_4 + 1.0*a_3*a_5 + a_3 - 0.5*a_4**2 + a_4 - 0.5*a_5**2 + a_5"
      ]
     },
     "execution_count": 259,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "eq = eq1-1/2*eq2\n",
    "eq"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 260,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-12-30T05:03:53.701888Z",
     "start_time": "2019-12-30T05:03:53.695865Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle 1$"
      ],
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 260,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sympy.diff(eq,\"a_1\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 261,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-12-30T05:03:53.721829Z",
     "start_time": "2019-12-30T05:03:53.702847Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle - 1.0 a_{2} + 1.0 a_{3} - 1.0 a_{5} + 1$"
      ],
      "text/plain": [
       "-1.0*a_2 + 1.0*a_3 - 1.0*a_5 + 1"
      ]
     },
     "execution_count": 261,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sympy.diff(eq,\"a_2\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 262,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-12-30T05:03:53.736783Z",
     "start_time": "2019-12-30T05:03:53.722793Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle 1.0 a_{2} - 2.0 a_{3} - 1.0 a_{4} + 1.0 a_{5} + 1$"
      ],
      "text/plain": [
       "1.0*a_2 - 2.0*a_3 - 1.0*a_4 + 1.0*a_5 + 1"
      ]
     },
     "execution_count": 262,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sympy.diff(eq,\"a_3\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 263,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-12-30T05:03:53.747754Z",
     "start_time": "2019-12-30T05:03:53.737753Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle - 1.0 a_{3} - 1.0 a_{4} + 1$"
      ],
      "text/plain": [
       "-1.0*a_3 - 1.0*a_4 + 1"
      ]
     },
     "execution_count": 263,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sympy.diff(eq,\"a_4\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 264,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle - 1.0 a_{2} + 1.0 a_{3} - 1.0 a_{5} + 1$"
      ],
      "text/plain": [
       "-1.0*a_2 + 1.0*a_3 - 1.0*a_5 + 1"
      ]
     },
     "execution_count": 264,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sympy.diff(eq,\"a_5\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 265,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-12-30T05:03:53.754711Z",
     "start_time": "2019-12-30T05:03:53.748723Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle a_{1} + a_{2} + a_{3} - a_{4} - a_{5}$"
      ],
      "text/plain": [
       "a_1 + a_2 + a_3 - a_4 - a_5"
      ]
     },
     "execution_count": 265,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sympy.Add(*[y[i]*a[i] for i in range(len(a))])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 求 $\\alpha_i$\n",
    "约束包括：\n",
    "- $\\sum_{i=1}^{n} y_i \\alpha_i=0$\n",
    "- $\\frac{\\partial A(\\alpha)}{\\partial\\alpha_i}=0$\n",
    "\n",
    "中间过程不等式约束需要手算"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 266,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-12-30T05:03:53.762686Z",
     "start_time": "2019-12-30T05:03:53.755705Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1,\n",
       " -1.0*a_2 + 1.0*a_3 - 1.0*a_5 + 1,\n",
       " 1.0*a_2 - 2.0*a_3 - 1.0*a_4 + 1.0*a_5 + 1,\n",
       " -1.0*a_3 - 1.0*a_4 + 1,\n",
       " -1.0*a_2 + 1.0*a_3 - 1.0*a_5 + 1,\n",
       " a_1 + a_2 + a_3 - a_4 - a_5]"
      ]
     },
     "execution_count": 266,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "lin = []\n",
    "for i in range(len(a)):\n",
    "    lin.append(sympy.diff(eq,a[i]))\n",
    "lin.append(sympy.Add(*[y[i]*a[i] for i in range(len(a))]))\n",
    "lin"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 267,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-12-30T05:03:53.770665Z",
     "start_time": "2019-12-30T05:03:53.763683Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle - 1.0 a_{2} + 1.0 a_{3} - 1.0 a_{5} + 1$"
      ],
      "text/plain": [
       "-1.0*a_2 + 1.0*a_3 - 1.0*a_5 + 1"
      ]
     },
     "execution_count": 267,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "lin[-2]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 268,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-12-30T05:03:53.777647Z",
     "start_time": "2019-12-30T05:03:53.771663Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle a_{4}$"
      ],
      "text/plain": [
       "a_4"
      ]
     },
     "execution_count": 268,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a[3]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 269,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-12-30T05:03:53.821559Z",
     "start_time": "2019-12-30T05:03:53.779642Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/latex": [
       "$\\displaystyle \\left\\{\\left( 3.0 a_{4} + 2.0 a_{5} - 5.0, \\  - 1.0 a_{4} - 1.0 a_{5} + 3.0, \\  2.0 - 1.0 a_{4}, \\  a_{4}, \\  a_{5}\\right)\\right\\}$"
      ],
      "text/plain": [
       "FiniteSet((3.0*a_4 + 2.0*a_5 - 5.0, -1.0*a_4 - 1.0*a_5 + 3.0, 2.0 - 1.0*a_4, a_4, a_5))"
      ]
     },
     "execution_count": 269,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sympy.linsolve([lin[2],lin[4],lin[5]],a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 243,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(0.20000000000000018, 0.0, 0.8, 0.2, 0.8)"
      ]
     },
     "execution_count": 243,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a4=0.2\n",
    "a5=0.8\n",
    "3*a4+2*a5-2,-a4-a5+1,1-a4,a4,a5"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**不等式约束，取一个合法值，手算得出，这个要人工看一下数据，a1点不是支撑向量，设置为0**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 252,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-12-30T05:05:39.202328Z",
     "start_time": "2019-12-30T05:05:39.197312Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[2, 0, 0, 1, 1]"
      ]
     },
     "execution_count": 252,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# a = [0.5,0,0.25,0.25] # a2一定是支撑向量，这个解不合法!!!\n",
    "a = [2,0,0,1,1]\n",
    "a"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 计算参数 $W^{*}=\\sum_{i=1}^{n}\\alpha_i y_i x_i$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 253,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-12-30T05:05:40.901388Z",
     "start_time": "2019-12-30T05:05:40.896401Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 1, -1])"
      ]
     },
     "execution_count": 253,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "w = 0\n",
    "for i in range(x.shape[0]):\n",
    "        w += a[i]*y[i]*x[i]\n",
    "w"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 计算参数b\n",
    "$a_i$的值大于0，对应于样本$i$是支持向量\n",
    "\n",
    "从支持向量的约束条件： $yi * ( W * Xi + b ) – 1 = 0 $\n",
    "\n",
    "当 $y_i = +1$ 类时，有 $b^* =   1- W *  X_i$                 \n",
    "\n",
    "当 $y_j = - 1$ 类时， 有 $b^* =  - 1- W * X_j$   \n",
    "\n",
    "合并两个公式\n",
    "$b^*=-\\frac{1}{2}W^{*T}(x^+ + x^-)$\n",
    "- $x^+$ 和 $x^-$ 是正负例各一个支持向量"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 254,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-12-30T05:09:07.821819Z",
     "start_time": "2019-12-30T05:09:07.817801Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.5"
      ]
     },
     "execution_count": 254,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b = -1/2*(w*(x[0]+x[4])).sum()\n",
    "b"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 最优分类面：$W^{*T}x+b^*=0$\n",
    " - 0.5x1 - 0.5x2 + 0.75 = 0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "tensorflow",
   "language": "python",
   "name": "tensorflow"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.9"
  },
  "latex_envs": {
   "LaTeX_envs_menu_present": true,
   "autoclose": false,
   "autocomplete": true,
   "bibliofile": "biblio.bib",
   "cite_by": "apalike",
   "current_citInitial": 1,
   "eqLabelWithNumbers": true,
   "eqNumInitial": 1,
   "hotkeys": {
    "equation": "Ctrl-E",
    "itemize": "Ctrl-I"
   },
   "labels_anchors": false,
   "latex_user_defs": false,
   "report_style_numbering": false,
   "user_envs_cfg": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
